package cn.sykj.car.service.impl;

import cn.sykj.car.common.Const;
import cn.sykj.car.entity.Region;
import cn.sykj.car.exception.CommonException;
import cn.sykj.car.exception.DictionaryDictException;
import cn.sykj.car.exception.ParameterInvalidException;
import cn.sykj.car.mapper.RegionMapper;
import cn.sykj.car.service.IRegionService;
import cn.sykj.car.utils.DiffEntityUtils;
import cn.sykj.car.utils.Utils;
import cn.sykj.car.vo.RegionVO;
import cn.sykj.car.vo.ResponseMessageVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 中国地区信息 服务实现类
 * </p>
 *
 * @author yixu
 * @since 2020-06-18
 */
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements IRegionService {

    /**
     * 根据模型id，查询未使用的配置地址
     *
     * @param mouldId
     * @return
     * @throws Exception
     */
    @Override
    public List<RegionVO> listNotExists(Long mouldId) throws Exception {

        if (Utils.isEmpty(mouldId)) {
            throw new ParameterInvalidException();
        }

        // 查询全部地址
        List<RegionVO> allList = baseMapper.all();

        // 查询已选中的配送区域
        List<RegionVO> exixtsList = baseMapper.listExistsAll(mouldId);

        // 定义返回值
        List<RegionVO> retList = new ArrayList<>();

        // 将全部可配送区域封装成Map
        Map<String, Map<String, Map<String, Map<String, String>>>> allMap = new HashMap<>();
        if (allList.size() > 0) {
            for (RegionVO allVO : allList) {

                // 大区
                Map<String, Map<String, Map<String, String>>> provinceAllMap = new HashMap<>();
                List<RegionVO> provinceList = allVO.getSubRegions();
                if (Utils.notEmpty(provinceList) && provinceList.size() > 0) {

                    // 省
                    for (RegionVO provinceVO : provinceList) {
                        Map<String, Map<String, String>> cityAllMap = new HashMap<>();
                        List<RegionVO> cityList = provinceVO.getSubRegions();
                        if (Utils.notEmpty(cityList) && cityList.size() > 0) {

                            // 市
                            for (RegionVO cityVO : cityList) {
                                Map<String, String> regionAllMap = new HashMap<>();
                                List<RegionVO> regionList = cityVO.getSubRegions();
                                if (Utils.notEmpty(regionList) && regionList.size() > 0) {

                                    // 区
                                    for (RegionVO regionVO : regionList) {
                                        regionAllMap.put(regionVO.getCode().concat("_").concat(regionVO.getName()), regionVO.getName());
                                    }
                                }
                                cityAllMap.put(cityVO.getCode().concat("_").concat(cityVO.getName()), regionAllMap);
                            }
                        }
                        provinceAllMap.put(provinceVO.getCode().concat("_").concat(provinceVO.getName()), cityAllMap);
                    }
                }
                allMap.put(allVO.getId().toString().concat("_").concat(allVO.getRegion()), provinceAllMap);
            }
        }

        // 将已选中的配送区域封装成Map
        Map<String, Map<String, Map<String, Map<String, String>>>> allExistsMap = new HashMap<>();
        if (exixtsList.size() > 0) {
            for (RegionVO allVO : exixtsList) {

                // 大区
                Map<String, Map<String, Map<String, String>>> provinceAllMap = new HashMap<>();
                List<RegionVO> provinceList = allVO.getSubRegions();
                if (Utils.notEmpty(provinceList) && provinceList.size() > 0) {

                    // 省
                    for (RegionVO provinceVO : provinceList) {
                        Map<String, Map<String, String>> cityAllMap = new HashMap<>();
                        List<RegionVO> cityList = provinceVO.getSubRegions();
                        if (Utils.notEmpty(cityList) && cityList.size() > 0) {

                            // 市
                            for (RegionVO cityVO : cityList) {
                                Map<String, String> regionAllMap = new HashMap<>();
                                List<RegionVO> regionList = cityVO.getSubRegions();
                                if (Utils.notEmpty(regionList) && regionList.size() > 0) {

                                    // 区
                                    for (RegionVO regionVO : regionList) {
                                        regionAllMap.put(regionVO.getCode().concat("_").concat(regionVO.getName()), regionVO.getName());
                                    }
                                }
                                cityAllMap.put(cityVO.getCode().concat("_").concat(cityVO.getName()), regionAllMap);
                            }
                        }
                        provinceAllMap.put(provinceVO.getCode().concat("_").concat(provinceVO.getName()), cityAllMap);
                    }
                }
                allExistsMap.put(allVO.getId().toString().concat("_").concat(allVO.getRegion()), provinceAllMap);
            }
        }

        // 遍历全部，从全部中去除掉已选中的，并封装成List，返回
        for (Map.Entry<String, Map<String, Map<String, Map<String, String>>>> aMap : allMap.entrySet()) {
            String allKey = aMap.getKey();
            Map<String, Map<String, Map<String, String>>> provinceMap = aMap.getValue();
            Map<String, Map<String, Map<String, String>>> existsProvinceMap = allExistsMap.get(allKey);
            List<RegionVO> provinceList = new ArrayList<>();

            RegionVO allVO = new RegionVO();
            allVO.setId(Integer.valueOf(allKey.split("_")[0]));
            allVO.setName(allKey.split("_")[1]);
            allVO.setRegion(allKey.split("_")[1]);

            for (Map.Entry<String, Map<String, Map<String, String>>> pMap : provinceMap.entrySet()) {
                String provinceKey = pMap.getKey();
                Map<String, Map<String, String>> cityMap = pMap.getValue();

                RegionVO provinceVO = new RegionVO();
                provinceVO.setCode(provinceKey.split("_")[0]);
                provinceVO.setName(provinceKey.split("_")[1]);

                List<RegionVO> cityList = new ArrayList<>();
                if (Utils.isEmpty(existsProvinceMap)) {
                    // 把全部市装入cityList
                    for (Map.Entry<String, Map<String, String>> cMap : cityMap.entrySet()) {
                        String cKey = cMap.getKey();
                        Map<String, String> cValues = cMap.getValue();

                        RegionVO cityVO = new RegionVO();
                        cityVO.setCode(cKey.split("_")[0]);
                        cityVO.setName(cKey.split("_")[1]);

                        List<RegionVO> regionList = new ArrayList<>();
                        if (cValues.size() > 0) {
                            for (Map.Entry<String, String> rMap : cValues.entrySet()) {
                                String rKey = rMap.getKey();
                                String rName = rMap.getValue();

                                RegionVO regionVO = new RegionVO();
                                regionVO.setCode(rKey.split("_")[0]);
                                regionVO.setName(rName);
                                regionList.add(regionVO);
                            }
                        }
                        cityVO.setSubRegions(regionList);
                        cityList.add(cityVO);
                    }
                } else {
                    Map<String, Map<String, String>> existsCityMap = existsProvinceMap.get(provinceKey);

                    for (Map.Entry<String, Map<String, String>> cMap : cityMap.entrySet()) {
                        String cityKey = cMap.getKey();
                        Map<String, String> regionMap = cMap.getValue();

                        RegionVO cityVO = new RegionVO();
                        cityVO.setCode(cityKey.split("_")[0]);
                        cityVO.setName(cityKey.split("_")[1]);

                        List<RegionVO> regionList = new ArrayList<>();
                        if (Utils.isEmpty(existsCityMap)) {

                            // 证明全部未被选中
                            for (Map.Entry<String, String> rMap : regionMap.entrySet()) {
                                RegionVO regionVO = new RegionVO();
                                regionVO.setCode(rMap.getKey().split("_")[0]);
                                regionVO.setName(rMap.getKey().split("_")[1]);
                                regionList.add(regionVO);
                            }
                            cityVO.setSubRegions(regionList);
                        } else {
                            Map<String, String> existsRegionMap = existsCityMap.get(cityKey);

                            if (Utils.isEmpty(existsRegionMap)) {

                                // 证明全部未被选中
                                for (Map.Entry<String, String> rMap : regionMap.entrySet()) {
                                    String key = rMap.getKey();
                                    String value = rMap.getValue();

                                    RegionVO regionVO = new RegionVO();
                                    regionVO.setCode(key.split("_")[0]);
                                    regionVO.setName(value);
                                    regionList.add(regionVO);
                                    cityVO.setSubRegions(regionList);
                                }
                            } else {
                                if (regionMap.size() == existsRegionMap.size()) {

                                } else if (regionMap.size() != existsRegionMap.size()) {
                                    for (Map.Entry<String, String> rMap : regionMap.entrySet()) {
                                        String key = rMap.getKey();
                                        String value = rMap.getValue();
                                        if (Utils.isEmpty(existsRegionMap.get(key))) {
                                            // 证明未被选中
                                            RegionVO regionVO = new RegionVO();
                                            regionVO.setCode(key.split("_")[0]);
                                            regionVO.setName(value);
                                            regionList.add(regionVO);
                                        }
                                    }
                                    cityVO.setSubRegions(regionList);
                                }
                            }
                        }
                        if (Utils.notEmpty(cityVO.getSubRegions()) && cityVO.getSubRegions().size() > 0) {
                            cityList.add(cityVO);
                        }
                    }
                }
                provinceVO.setSubRegions(cityList);
                if (provinceVO.getSubRegions().size() > 0) {
                    provinceList.add(provinceVO);
                }
            }
            allVO.setSubRegions(provinceList);
            if (allVO.getSubRegions().size() > 0) {
                retList.add(allVO);
            }
        }

        Collections.sort(retList, new Comparator<RegionVO>() {
            @Override
            public int compare(RegionVO o1, RegionVO o2) {
                return o1.getRegion().compareTo(o2.getRegion());
            }
        });
        return retList;
    }

    /**
     * 根据配送区域配置freight_model_detail.id 获取已选中的配送区域
     *
     * @param mouldDetailId
     * @return
     * @throws Exception
     */
    @Override
    public List<RegionVO> listExists(Long mouldDetailId) throws Exception {

        if (Utils.isEmpty(mouldDetailId)) {
            throw new ParameterInvalidException();
        }

        return baseMapper.listExists(mouldDetailId);
    }

    /**
     * 查询全部
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<RegionVO> all() throws Exception {
        return baseMapper.all();
    }

    @Override
    public List<RegionVO> listL3() throws Exception {
        List<RegionVO> list = baseMapper.selectForL3();
        return list;
    }

    /**
     * 添加地区
     *
     * @param region
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public ResponseMessageVO addRegion(Region region) throws Exception {

        // 验证参数非空
        if (Utils.isEmpty(region)) {
            throw new ParameterInvalidException();
        }

        // 验证业务逻辑
        // 如果是省级行政单位
        if (Utils.isEmpty(region.getPCode())) {
            region.setPCode("000000");// 首层-省级行政单位p_code赋值为000000
        }
        // 验证输入的region的code name short_name是否为空，且是否重复
        if (Utils.isEmpty(region.getCode())
                || Utils.isEmpty(region.getName())
                || Utils.isEmpty(region.getShotName())) {
            throw new CommonException("", "行政区划中的code编码、全称、简称均不能为空！");
        }

        QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.CODE, region.getCode());
        List<Region> codeRegionList = this.list(queryWrapper);
        if (!codeRegionList.isEmpty() && codeRegionList.size() != 0) {
            throw new CommonException("", "行政区域code编码重复！");
        }

        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.NAME, region.getName());
        List<Region> nameRegionList = this.list(queryWrapper);
        if (!nameRegionList.isEmpty() && nameRegionList.size() != 0) {
            throw new CommonException("", "行政区域全称不能重复！");
        }

        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.SHOT_NAME, region.getShotName());
        List<Region> shotNameRegionList = this.list(queryWrapper);
        if (!shotNameRegionList.isEmpty() && shotNameRegionList.size() != 0) {
            throw new CommonException("", "行政区域简称不能重复!");
        }

        // 验证所在区域，是否在华东、华南、华中、华北、西北、西南、东北、海外、港澳台
        List<String> regionList = new ArrayList<>();
        regionList.add("华东");
        regionList.add("华南");
        regionList.add("华中");
        regionList.add("华北");
        regionList.add("西北");
        regionList.add("西南");
        regionList.add("东北");
        regionList.add("海外");
        regionList.add("港澳台");

        if(!regionList.contains(region.getRegion())){
            throw new CommonException("","行政区域必须选择华东、华南、华中、华北、西北、西南、东北、海外、港澳台标签");
        }

        // 通过p_code获取其行政区，若P_CODE=000000，证明是顶级行政区
        if(region.getPCode().equals("000000")){
            region.setLevel("1");
        }else{
            // 获取其上级行政区域
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(Region.CODE,region.getPCode());
            Region upRegion = this.getOne(queryWrapper);
            if(Utils.isEmpty(upRegion)){
                throw new CommonException("","上级区域编码不存在！");
            }
            if(!upRegion.getRegion().equals(region.getRegion())){
                throw new CommonException("","上级所属大区与当前区域所属大区不一致！");
            }

            if(upRegion.getLevel().equals("1")){
                region.setLevel("2");
            }else if(upRegion.getLevel().equals("2")){
                region.setLevel("3");
            }else if(upRegion.getLevel().equals("3")){
                region.setLevel("4");
            }
        }

        // 保存
        boolean ret = this.save(region);

        // 构建操作日志参数
        ResponseMessageVO responseMessageVO = new ResponseMessageVO();
        responseMessageVO.setRetType("添加地区");
        responseMessageVO.setRetFlag(ret);
        responseMessageVO.setRetMsg("添加地区，ID为：" + region.getId()+";"+"添加地区:"+region.getName());
        return responseMessageVO;
    }

    /**
     * 删除地区
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public ResponseMessageVO delete(Integer id) throws Exception {

        // 查询原始数据是否存在
        Region oldRegion = this.getById(id);
        if(Utils.isEmpty(oldRegion)){
            throw new CommonException("","原始记录不存在，无需删除！");
        }

        // 查询一下，该级别行政区域是否存在下级
        QueryWrapper<Region> childQueryWrapper = new QueryWrapper<>();
        childQueryWrapper.eq(Region.P_CODE,oldRegion.getCode());
        int cnt = this.count(childQueryWrapper);
        if(cnt > 0){
            throw new CommonException("","该级别行政区域有子级行政区域，不能删除！");
        }

        boolean ret = this.removeById(id);

        // 构建操作日志参数
        ResponseMessageVO responseMessageVO = new ResponseMessageVO();
        responseMessageVO.setRetType("删除地区");
        responseMessageVO.setRetFlag(ret);
        responseMessageVO.setRetMsg("删除地区，ID为：" + oldRegion.getId()+";"+"删除地区:"+oldRegion.getName());
        return responseMessageVO;
    }

    /**
     * 修改地区
     *
     * @param region
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public ResponseMessageVO updateRegion(Region region) throws Exception {
        //验证参数是否为空
        if(Utils.isEmpty(region)||Utils.isEmpty(region.getId())){
            throw new ParameterInvalidException();
        }
        //判断原始记录是否存在
        Region reg=this.getById(region.getId());
        if(Utils.isEmpty(reg)||reg.getDelFlag().equals(Const.DEL_FLAG_TRUE)){
            throw new DictionaryDictException("","记录不存在");
        }

        // 验证业务逻辑
        // 如果是省级行政单位
        if (Utils.isEmpty(region.getPCode())) {
            region.setPCode("000000");// 首层-省级行政单位p_code赋值为000000
        }
        // 验证输入的region的code name short_name是否为空，且是否重复
        if (Utils.isEmpty(region.getCode())
                || Utils.isEmpty(region.getName())
                || Utils.isEmpty(region.getShotName())) {
            throw new CommonException("", "行政区划中的code编码、全称、简称均不能为空！");
        }

        // 验证除了本身之外有没有code编码重复
        QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.CODE, region.getCode());
        queryWrapper.ne(Region.ID,region.getId());
        List<Region> codeRegionList = this.list(queryWrapper);
        if (!codeRegionList.isEmpty() && codeRegionList.size() != 0) {
            throw new CommonException("", "行政区域code编码重复！");
        }

        // 验证除了本身之外有没有name重复
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.NAME, region.getName());
        queryWrapper.ne(Region.ID,region.getId());
        List<Region> nameRegionList = this.list(queryWrapper);
        if (!nameRegionList.isEmpty() && nameRegionList.size() != 0) {
            throw new CommonException("", "行政区域全称不能重复！");
        }

        // 验证除了本身之外有没有shotName重复
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Region.P_CODE, region.getPCode());
        queryWrapper.eq(Region.SHOT_NAME, region.getShotName());
        queryWrapper.ne(Region.ID,region.getId());
        List<Region> shotNameRegionList = this.list(queryWrapper);
        if (!shotNameRegionList.isEmpty() && shotNameRegionList.size() != 0) {
            throw new CommonException("", "行政区域简称不能重复!");
        }

        // 验证所在区域，是否在华东、华南、华中、华北、西北、西南、东北、海外、港澳台
        List<String> regionList = new ArrayList<>();
        regionList.add("华东");
        regionList.add("华南");
        regionList.add("华中");
        regionList.add("华北");
        regionList.add("西北");
        regionList.add("西南");
        regionList.add("东北");
        regionList.add("海外");
        regionList.add("港澳台");

        if(!regionList.contains(region.getRegion())){
            throw new CommonException("","行政区域必须选择华东、华南、华中、华北、西北、西南、东北、海外、港澳台标签");
        }

        // 通过p_code获取其行政区，若P_CODE=000000，证明是顶级行政区
        if(region.getPCode().equals("000000")){
            region.setLevel("1");
        }else{
            // 获取其上级行政区域
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(Region.CODE,region.getPCode());
            Region upRegion = this.getOne(queryWrapper);
            if(Utils.isEmpty(upRegion)){
                throw new CommonException("","上级区域编码不存在！");
            }
            if(!upRegion.getRegion().equals(region.getRegion())){
                throw new CommonException("","上级所属大区与当前区域所属大区不一致！");
            }

            if(upRegion.getLevel().equals("1")){
                region.setLevel("2");
            }else if(upRegion.getLevel().equals("2")){
                region.setLevel("3");
            }else if(upRegion.getLevel().equals("3")){
                region.setLevel("4");
            }
        }

        // 把要更新的对象中的属性，覆盖到已有对象中
        boolean ret = this.updateById(region);
        // 定义修改字符串：
        String editMes = "";

        // 遍历修改的内容与原始内容相比较，如果有变更，则记录
        Region afterCarStore = this.getById(region.getId());
        Map<String,List<Object>> diffMap = DiffEntityUtils.getDifferent(reg,afterCarStore);
        if(Utils.notEmpty(diffMap) && diffMap.size() > 0){
            for(String s : diffMap.keySet()){
                editMes = editMes + ">" + s + "==>修改前【" + diffMap.get(s).get(0) + "】-修改后【" + diffMap.get(s).get(1) + "】;";
            }
        }

        ResponseMessageVO responseMessageVO = new ResponseMessageVO();
        responseMessageVO.setRetType("修改地区");
        responseMessageVO.setRetFlag(ret);
        responseMessageVO.setRetMsg("修改地区，ID为：" + afterCarStore.getId() + ";具体修改信息为：" + editMes);
        return responseMessageVO;
    }

}
